/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package ig.metrica.ui.matriz.correlacion.calculada.modelo;

import ig.finanzas.LibreriaOperacionesEstadisticas;
import ig.finanzas.LibreriaOperacionesFinancieras;
import ig.metrica.riesgo.FactorRiesgoMatrizCorrelacionMetrica;
import ig.metrica.ui.matriz.correlacion.calculada.PFactores;
import ig.util.MyTableModel;
import ig.util.excepciones.DatoInvalidoExcepcion;
import ig.util.excepciones.LogicaExcepcion;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Enumeration;
import java.util.Hashtable;

/**
 *
 * @author Jimmy
 */
public class MFactores implements IModeloWizzar {

    public Double desviacion(Object[][] get) throws DatoInvalidoExcepcion {
        Collection coll = new ArrayList();
        for (int i = 0; i < get.length; i++) {
            coll.add(Double.valueOf(get[i][4].toString()));
        }
        return LibreriaOperacionesEstadisticas.desviacion(coll);
    }

    public Object[][] getData(Object obj) {
        if (obj instanceof Collection) {
            datos = (Collection<ArrayList>) obj;
            Hashtable<String, Integer> ht = new Hashtable<String, Integer>();

            for (ArrayList<Object[]> objects_ : datos) {
                for (Object[] objects : objects_) {
                    if (!(objects instanceof String[])) {
                        if (ht.get(objects[0]) == null) {
                            ht.put(objects[0].toString(), 1);
                        } else {
                            ht.put(objects[0].toString(), ht.get(objects[0].toString()) + 1);
                        }
                    }
                }
            }
            Object[][] data = new Object[ht.size()][4];
            int i = 0;
            Enumeration<String> enumm = ht.keys();
            while (enumm.hasMoreElements()) {
                String string = enumm.nextElement();
                data[i][0] = string;
                data[i][1] = ht.get(string);
                data[i][2] = "";
                data[i++][3] = false;
            }
            return data;
        } else if (obj instanceof String) {
            if (datos == null || datos.size() == 0) {
                return null;
            }
            Collection<Object[]> filtrada = new ArrayList<Object[]>();
            for (ArrayList<Object[]> objects_ : datos) {
                for (Object[] objects : objects_) {
                    if (objects[0].equals(obj)) {
                        filtrada.add(objects);
                    }
                }
            }
            Object[][] data = new Object[filtrada.size()][5];
            int i = 0;
            for (Object[] objects : filtrada) {
                data[i][0] = objects[0];
                data[i][1] = objects[1];
                data[i][2] = objects[2];
                data[i][3] = objects[3];
                data[i++][4] = objects[4];
            }
            return data;
        }
        return null;
    }

    public Double promedio(Object[][] get) {
        Double promedio = 0D;
        for (int i = 0; i < get.length; i++) {
            promedio += Double.valueOf(get[i][4].toString());
        }
        return promedio / get.length;

    }

    public void siguiente() throws Exception {
        p = new proceso();
        p.start();
    }

    public void finalizar() throws Exception {
        throw new UnsupportedOperationException("Not supported yet.");
    }

    public void calcelar() throws Exception {
        throw new UnsupportedOperationException("Not supported yet.");
    }

    public void setObject(Object obj) throws Exception {

    }

    public Object getObject() {
        throw new UnsupportedOperationException("Not supported yet.");
    }

    public boolean isSiguiente() {
        return p.isFinalizado();
    }

    public String getErrores() {
        return errores;
    }

    class proceso extends Thread {

        boolean finalizado = false;

        @Override
        public void run() {
            super.run();
            errores = null;
            Hashtable<String, Object[][]> hashtable = new Hashtable<String, Object[][]>();
            Hashtable<String, Integer> hashtableP = new Hashtable<String, Integer>();

            Object[][] data = ((MyTableModel) panel.getFACTORES().getModel()).getData();//los datos de la tabla factor
            int j = 0;
            for (int i = 0; i < data.length; i++) {
                if ((Boolean) data[i][3]) {//si el factor esta seleccionado
                    Object[][] datos = getData(panel.getFACTORES().getValueAt(i, 0).toString());
                    for (int k = 0; k < datos.length; k++) {
                        if (datos[k][1].toString().trim().toUpperCase().equals("C") || datos[k][1].toString().trim().toUpperCase().equals("CURVA")) {
                            if (panel.getFACTORES().getValueAt(i, 2).toString().trim() == null || panel.getFACTORES().getValueAt(i, 2).toString().trim().equals("")) {
                                errores = "Para factores tipo Cupon, el pazo es requerido.";
                                hashtable.clear();
                                break;
                            } else {
                                String[] plazos = panel.getFACTORES().getValueAt(i, 2).toString().trim().split(",");//cada uno de los plazos
                                int contador = 0;
                                Double[] valores = new Double[4];
                                for (int l = 0; l < datos.length; l++) {//con cada una de las filas de la tabla datos
                                    //3 es la posicion en la tablas datos
                                    //4 es el valor en ls tabla datos
                                    valores[Integer.valueOf(datos[l][3].toString())] = Double.valueOf(datos[l][4].toString());
                                    valores[0] = Double.valueOf(datos[l][4].toString());
                                    valores[1] = Double.valueOf(datos[l][4].toString());
                                    valores[2] = Double.valueOf(datos[l][4].toString());
                                    contador++;
                                    if (contador == 4) {
                                        contador = 0;
                                        try {
                                            //hacer el calculo 
                                            for (int m = 0; m < plazos.length; m++) {
                                                if (plazos[m] != null && !plazos[m].trim().equals("")) {
                                                    Integer plazo = Integer.valueOf(plazos[m]);//cada uno de los plazos
                                                    Double curva = LibreriaOperacionesFinancieras.valorTasaCurva(valores[0], valores[1], valores[2], valores[3], plazo);
                                                    datos[l][4] = curva;
                                                    //                                                        System.out.print("curva:"+curva);
                                                    hashtable.put(data[i][0].toString() + "_" + plazo, datos);
                                                    hashtableP.put(data[i][0].toString() + "_" + plazo, j++);
                                                }
                                            }
                                        } catch (LogicaExcepcion ex) {
                                            errores = ex.getMessage() + "\n" + ex.getPosibleSolucion();
                                        } catch (DatoInvalidoExcepcion ex) {
                                            errores = ex.getMessage() + "\n" + ex.getPosibleSolucion();
                                        } catch (NullPointerException ex) {
                                            errores = "Falta una de las posiciones" + "\n" + "Verifique la consulta.";
                                        } catch (NumberFormatException ex) {
                                            errores = "Posible plazo no numerico" + "\n" + "Verifique uno de los plazos.";
                                        }
                                    }
                                }
                            }
                        } else {
                            hashtable.put(data[i][0].toString(), datos);
                            hashtableP.put(data[i][0].toString(), j++);
                        }
                    }//for k
                }
            }


            matriz = new Double[hashtable.size()][hashtable.size()];
            Enumeration<String> filas = hashtable.keys();
            factores = new ArrayList<FactorRiesgoMatrizCorrelacionMetrica>();
            int k = 0;
            int l = 0;
            try {
                while (filas.hasMoreElements()) {
                    String n_fila = filas.nextElement();
                    k = hashtableP.get(n_fila);
                    FactorRiesgoMatrizCorrelacionMetrica f = new FactorRiesgoMatrizCorrelacionMetrica(n_fila, 0, k + 1, -1);
                    f.setNuevo(true);
                    factores.add(f);

                    Double promedioF = promedio(hashtable.get(n_fila));
                    Double desviacionF = desviacion(hashtable.get(n_fila));

                    Double TOTAL = 0D;

                    Enumeration<String> columnas = hashtable.keys();
                    while (columnas.hasMoreElements()) {
                        String n_columna = columnas.nextElement();
                        l = hashtableP.get(n_columna);

                        Double promedioC = promedio(hashtable.get(n_columna));
                        Double desviacionC = desviacion(hashtable.get(n_columna));
                        if (l == k) {
                            matriz[l][k] = 1D;
                        } else {
                            for (int i = 0; i < hashtable.get(n_fila).length; i++) {
                                Double DATOS_F = Double.valueOf(hashtable.get(n_fila)[i][4].toString());//el valor del una serie
                                DATOS_F -= promedioF;

                                Double DATOS_C = Double.valueOf(hashtable.get(n_columna)[i][4].toString());// el valor de una serie
                                DATOS_C -= promedioC;
                                DATOS_F *= DATOS_C;

                                TOTAL += DATOS_F;
                            }
                            TOTAL /= hashtable.get(n_fila).length;
                            TOTAL /= (desviacionF * desviacionC);
                            if (!TOTAL.isNaN() && matriz[l][k] == null) {
                                matriz[l][k] = TOTAL;
                                matriz[k][l] = TOTAL;
                            }
                        }
                    }
                }
//                for (int i = 0; i < matriz.length; i++) {
//                    System.out.println("");
//                    for (int m = 0; m < matriz.length; m++) {
//                        System.out.print(matriz[i][m]+"\t");
//                    }
//                }                
            } catch (ArrayIndexOutOfBoundsException ex) {
                ex.printStackTrace();
                errores = "Se está repitiendo un plazo para un factor tipo Cupon" + "\n" + "Verifique los plazos";
            } catch (DatoInvalidoExcepcion ex) {
                ex.printStackTrace();
                errores = ex.getMessage() + "\n" + ex.getPosibleSolucion();
            }
            finalizado = true;
        }

        public boolean isFinalizado() {
            return finalizado;
        }
    }
    private Double[][] matriz = null;
    private Collection<FactorRiesgoMatrizCorrelacionMetrica> factores = null;
    private String errores = null;
    private proceso p = null;
    private Collection<ArrayList> datos = null;
    private PFactores panel = null;

    public Double[][] getMatriz() {
        return matriz;
    }

    public Collection<FactorRiesgoMatrizCorrelacionMetrica> getFactores() {
        return factores;
    }

}
